home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * *** HAPPy Pascal Compiler ***
- * P-code assmebler
- *
- * Copyright (c) H.Asano 1992-1994.
- *
- **********************************************************************/
-
- #define EXTERN extern
- #define Maxlabel 500 /* 最大ラベル数 */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "version.h"
- #include "hapai.h"
-
- /********* co-operation table **********/
- static char cop[] = {
- 115/*lod*/, 105/*ldo*/, 125/*str*/, 120/*sro*/,
- 130/*sto*/, 110/*chk*/, 135/*ind*/ } ;
-
- /***************************************/
- /* ラベル表 */
- /***************************************/
- enum lbst { entered, /* ラベル未登録の状態 */
- defined /* ラベル定義済の状態 */
- };
-
- static struct {
- short val ; /* value */
- enum lbst st ; /* status {enterd,defined} */
- } labeltab[Maxlabel] ;
-
- /***************************************/
- /* 仮想計算機 記憶装置 */
- /***************************************/
- static _store store[Maxstore] ;
-
- /***************************************/
- /* 変数定義 */
- /***************************************/
- static char *PcodeSourceName ; /* P-codeソースファイル名 */
- static char *PcodeObjectName ; /* P-codeオブジェクトファイル名 */
- static char *CompVersion ; /* コンパイラのバージョン */
- static FILE *pcsfile ; /* P-codeソースファイルポインタ */
- static FILE *objfile ; /* P-codeオブジェクトファイルポインタ */
- static short codesize ; /* コードのワードサイズ */
- static short objsize ; /* オブジェクト全体のワードサイズ */
- static short ch ; /* 読込文字 */
- static short intch ; /* 読込処理内での読込文字 */
- static short pc ; /* program counter */
- static _code cd ; /* P-code */
- static short entpc ; /* ent命令の番地 */
- static short start = -1 ; /* オブジェクト開始の合図 */
-
- /*********************************************************************/
-
- /***************************************/
- /* エラーメッセージ出力処理 */
- /***************************************/
- static void paerr(short errno)
- {
- static struct _errmsg {
- short msgno ; /* error message number */
- char *errmsg ; /* error message */
- } errtb[] = {
-
- {1, "命令数が多すぎる"},
- {2, "オブジェクトファイルがオープンできない"},
- {3, "オブジェクトファイル出力でエラーが発生した"},
- {4, "ラベルが多する"},
- {5, "定数が多すぎる"},
- {6, "P-codeソースファイルがオープンできない"},
- {7, "PC.EXEとPA.OVLのバージョンが違う"},
- {8, "アセンブルリストの出力でエラーが発生した"}
- } ;
- short i = -1 ;
-
- while(errtb[++i].msgno != errno) ; /* search message */
- fprintf(stderr,"A%03d: %s\n", errno, errtb[i].errmsg);
- exit(3) ; /* アセンブルエラーで停止 */
- }
-
- /***************************************/
- /* reset() : reset関数 */
- /***************************************/
- static void reset(char *filename)
- {
-
- pcsfile = fopen(filename,"r") ;
- if(pcsfile == NULL) paerr(6) ;
-
- intch = getc(pcsfile) ; /* 1文字先読み */
- }
-
- /***************************************/
- /* eoln() : eolnマクロ定義 */
- /***************************************/
- #define eoln() (intch == '\n') /* 改行を読んでいれば真 */
-
- /***************************************/
- /* readc() : char型read処理 */
- /***************************************/
- static short readc(void)
- {
- short oldch ;
-
- oldch = intch ;
- intch = getc(pcsfile) ;
- return(oldch) ;
- }
-
- /***************************************/
- /* readi() : integer型入力処理 */
- /***************************************/
- static integer readi(void)
- {
- integer ival = 0 ;
- short sign = 1 ;
-
- if(intch == ' ')
- while((intch = getc(pcsfile)) == ' '); /* 空白読み飛ばし */
-
- if(intch=='-') { /* 符号の時 ( + は現れない) */
- sign = -1 ; /* 符号に応じた正負 */
- intch = getc(pcsfile) ; /* 符号を読み飛ばす */
- }
-
- do {
- ival = ival*10 + intch-'0' ;
- intch=getc(pcsfile) ;
- } while(('0' <= intch) && (intch <= '9')) ;
-
- return(sign*ival) ;
- }
-
- /***************************************/
- /* readr() : real型入力処理 */
- /***************************************/
- static float readr(void)
- {
- char buf[20] ;
- short i = 0 ;
-
- while(intch == ' ') intch = getc(pcsfile) ; /* 空白読み飛ばし */
- do {
- buf[i++] = (char)intch ;
- intch = getc(pcsfile) ;
- } while (intch != '\n') ;
- buf[i] = '\0' ;
-
- return((float)atof(buf)) ; /* 浮動小数点へ変換 */
- }
-
- /***************************************/
- /* readln() : EOLまで読み飛ばす処理 */
- /***************************************/
- static void readln(void)
- {
- while(!eoln()) intch = getc(pcsfile) ;
- intch = getc(pcsfile);
- }
-
- /***************************************/
- /* オブジェクトファイル書出処理 */
- /***************************************/
- static void putobject(char *area, short size)
- {
- fwrite(area,size,1,objfile) ;
- if(ferror(objfile)) paerr(3) ; /* 書き込み失敗 */
- }
-
- /***************************************/
- /* 初期設定処理 */
- /***************************************/
- static void init(void)
- {
- short i;
-
- for(i=0;i<Maxlabel;i++) { /* ラベル表 の 初期設定 */
- labeltab[i].val = -1 ;
- labeltab[i].st = entered;
- }
-
- reset(PcodeSourceName) ; /* P-codeソースファイルのオープン */
-
- objfile = fopen(PcodeObjectName,"wb") ;/* ファイルオープン */
- if(objfile == NULL) paerr(2) ; /* オープンできない */
-
- if(codesize > Maxstore) /* 記憶装置の大きさより大きい時*/
- paerr(1) ; /* プログラム停止 */
-
- if(strcmp(CompVersion,version))
- paerr(7) ; /* バージョン不一致 */
-
- putobject(version,strlen(version)+1) ; /* バージョン番号書出 */
-
- objsize = codesize ;
- }
-
- /***************************************/
- /* ラベル表登録処理 */
- /***************************************/
- static void update(void)
- {
- short x ; /* x: label名 */
- short curr,succ ;
-
- x=(short)readi() ; /* ラベル名を読む */
- if(x >= Maxlabel) paerr(4) ; /* ラベル数が多すぎる */
-
- if(labeltab[x].val != -1) { /* 前方参照されている時 */
- curr = labeltab[x].val;
- do {
- succ = store[curr].vo.q;
- store[curr].vo.q = pc ;
- curr = succ ;
- } while(succ != -1) ;
- }
- labeltab[x].st = defined ;
- labeltab[x].val = pc ;
- }
-
- /***************************************/
- /* ラベル値読込処理 */
- /***************************************/
- static void labelsearch(void)
- {
- short x ;
-
- while(ch != 'L') ch = readc() ; /* 'L' まで 読み飛ばし */
- x = (short)readi() ;
- if(x >= Maxlabel) paerr(4) ; /* ラベル数が多すぎる */
- if(labeltab[x].st == entered) { /* 未定義 */
- cd.q = labeltab[x].val ; /* 初期値のまま -1 */
- labeltab[x].val = pc ; /* 今のpcを格納 */
- }
- else cd.q = labeltab[x].val ; /* 定義済の時 */
- }
-
-
- /********* typesymbol() : instruction名4文字目によってopを決定する *********/
- static void typesymbol(void)
- {
- short i;
-
- switch(ch) {
- case 'i' : return ; /* 'i' の時は opはそのまま */
- case 'a' : i=0; break;
- case 'r' : i=1; break;
- case 's' : i=2; break;
- case 'b' : i=3; break;
- case 'c' : i=4;
- }
- cd.op=cop[cd.op]+i; /* opの変更 */
- }
-
- /**************************************/
- /* PTN0() : オペランドのない命令 */
- /**************************************/
- static void PTN0(void)
- {
- }
-
- /**************************************/
- /* PTN1() : lod,strのアセンブル */
- /**************************************/
- static void PTN1(void)
- {
- typesymbol() ;
- cd.p=(char)readi() ;
- cd.q=(short)readi() ;
- }
-
- /**************************************/
- /* PTN2() : lda,mov,wrsのアセンブル */
- /**************************************/
- static void PTN2(void)
- {
- cd.p=(char)readi() ;
- cd.q=(short)readi() ;
- }
-
- /*********************************************/
- /* PTN3() : mst,cui,bas,tra.mms, */
- /* eol,eof,pge,rln,rdc,rdi,rdr,tgt, */
- /* tgt,tpt,trs,trw,wln,wrb,wrc,wrf, */
- /* wri,wrr のアセンブル */
- /*********************************************/
- static void PTN3(void)
- {
- cd.p=(char)readi() ;
- }
-
- /**************************************/
- /* PTN4() : cup,ejpのアセンブル */
- /**************************************/
- static void PTN4(void)
- {
- cd.p=(char)readi() ;
- labelsearch();
- }
-
- /************************************************/
- /* PTN5() : equ,neq,geq,grt,leq,lesのアセンブル */
- /************************************************/
- static void PTN5(void)
- {
- switch(ch) {
- /*case 'a' : ; break ; 何もしない */
- case 'i' : cd.p=1 ; break ;
- case 'r' : cd.p=2 ; break ;
- case 'b' : cd.p=3 ; break ;
- case 's' : cd.p=4 ; break ;
- case 'c' : cd.p=6 ; break ;
- case 'm' : cd.p=5 ;
- cd.q=(short)readi() ;
- }
- }
-
- /**************************************/
- /* PTN6() : ldo,sro,indのアセンブル */
- /**************************************/
- static void PTN6(void)
- {
- typesymbol() ;
- cd.q=(short)readi();
- }
-
- /****************************************/
- /* PTN7() : inc,dec,nxt,nxdのアセンブル */
- /****************************************/
- static void PTN7(void)
- {
- switch(ch) {
- /*case 'a' : cd.p=0; break ; 何もしない */ /* inc,decのみ */
- case 'i' : cd.p=1; break ;
- case 'b' : cd.p=3; break ;
- case 'c' : cd.p=6; break ;
- }
- cd.q = (short)readi() ;
- }
-
- /****************************************/
- /* PTN8() : ujp,fjp,lapのアセンブル */
- /****************************************/
- #define PTN8 labelsearch
-
- /***************************************/
- /* PTN9() : lao,new,disのアセンブル */
- /***************************************/
- static void PTN9(void)
- {
- cd.q=(short)readi();
- }
-
- /**************************************/
- /* ENT() : entのアセンブル */
- /**************************************/
- static void ENT(void)
- {
- entpc = pc ;
- }
-
- /**************************************/
- /* CHK() : chkのアセンブル */
- /**************************************/
- static void CHK(void)
- {
- integer lb,ub ;
-
- typesymbol() ;
- cd.p = (char)readi() ; /* チェック種別 */
- lb = readi(); /* 下限値 */
- ub = readi(); /* 上限値 */
- if(objsize+1>=Maxstore) paerr(5) ; /* 定数格納不可 */
- store[objsize ].vi = lb ;
- store[objsize+1].vi = ub ;
- cd.q=codesize;
- do {
- cd.q++ ;
- } while((store[cd.q-1].vi != lb) || (store[cd.q].vi != ub)) ;
- if(cd.q == objsize) objsize++ ;/* 最後に1つだけ定数追加の時 */
- if(cd.q-1 == objsize) objsize += 2;/* 最後に2つの 対数追加の時 */
- }
-
- /**************************************/
- /* IXA() : ixaのアセンブル */
- /**************************************/
- static void IXA(void)
- {
- integer low ;
- short ixav ;
-
- low = readi() ; /* 下限値 */
- ixav = (short)readi() ; /* ixa値 */
- if(objsize+1>=Maxstore) paerr(5) ; /* 定数格納不可 */
- store[objsize ].vi = low ;
- store[objsize+1].va = ixav ; /* 2バイトエリアを使用 */
- cd.q=codesize;
- do {
- cd.q++ ;
- } while((store[cd.q-1].vi != low) || (store[cd.q].va != ixav)) ;
- if(cd.q == objsize) objsize++ ;/* 最後に1つだけ定数追加の時 */
- if(cd.q-1 == objsize) objsize += 2;/* 最後に2つの 対数追加の時 */
- }
-
- /**************************************/
- /* LCA() : lcaのアセンブル */
- /**************************************/
- /* lca '文字列'\n という形式とする。最後が改行で終わる。最初の ' と
- 改行の前の ' は P-codeソースを読む人間にわかりやすいようについているだけ */
-
- static void LCA(void)
- {
- cd.q=objsize;
- readc() ; /* 最初の ' を読み飛ばす */
- while(!eoln()) { /* 改行までの文字列を格納 */
- if(objsize+1>=Maxstore) paerr(5); /* 定数格納不可 */
- store[objsize++].vc = readc() ;
- }
- objsize-- ; /* 最後の ' を捨てる */
- }
-
- /**************************************/
- /* checkConst() : 定数格納チェック */
- /**************************************/
- static void checkConst(void)
- {
- if(cd.q==objsize) {
- if(objsize+1>=Maxstore) paerr(5); /* 定数格納不可 */
- objsize++ ;
- }
- }
-
- /**************************************/
- /* LDC() : ldcのアセンブル */
- /**************************************/
- static void LDC(void)
- {
- integer inumber ;
- float rnumber ;
- long s ;
-
- switch(ch) {
- case 'i' : cd.p=1 ; /* integer type */
- inumber = readi() ;
- if(labs(inumber) < (long)Largeint)
- cd.q = (short)inumber;
- else { /* 大きな数の時 */
- cd.op = 66 ; /* lci命令に変更 */
- store[objsize].vi = inumber ;
- cd.q = codesize ;
- while(store[cd.q].vi != inumber) cd.q++ ;
- checkConst() ; /* 定数格納チェック */
- }
- break ;
-
- case 'c' : cd.p=6 ; /* char type */
- while(readc() != '\'');/* 最初の ' を見つける */
- cd.q=readc() ; /* 文字を読み込む */
- break ; /* 最後の ' は無視する */
-
- case 'b' : cd.p=3; /* boolean */
- cd.q=(short)readi() ;
- break;
-
- case 's' : cd.p = 4; /* set type */
- s=0;
- while(readc() != '(') ;
- while(readc() != ')') addset(s,(short)readi()) ;
- store[objsize].vs = s ;
- cd.q = codesize ;
- while(store[cd.q].vs != s) cd.q++ ;
- checkConst() ; /* 定数格納チェック */
- break ;
-
- case 'r' : cd.p = 2 ;
- rnumber = readr() ;
- store[objsize].vr = rnumber ;
- inumber = store[objsize].vi ;
- /* 浮動小数点の形で比較を行うと思わぬ落とし穴があるので
- ビット列の比較をするために、union型のviから数を得る*/
- cd.q = codesize ;
- while(store[cd.q].vi != inumber) cd.q++ ;
- checkConst() ; /* 定数格納チェック */
- break ;
-
- /*case 'n' : cd.p=0 ; */ /* ldc nil */
- /* cd.q=0 ; */
- }
- }
-
- /**************************************/
- /* ORD() : ordのアセンブル */
- /**************************************/
- static void ORD(void)
- {
- switch(ch) {
- case 'b' : cd.p=3 ; break ;
- case 'c' : cd.p=6 ;
- }
- }
-
- /**************************************/
- /* RET() : retのアセンブル */
- /**************************************/
- static void RET(void)
- {
- switch(ch) {
- /*case 'p' : ; break ; 何もしない */
- case 'i' : cd.p=1 ; break ;
- case 'r' : cd.p=2 ; break ;
- case 'c' : cd.p=3 ; break ;
- case 'b' : cd.p=4 ; break ;
- case 'a' : cd.p=5 ; break ;
- }
- }
-
- /**************************************/
- /* STO() : stoのアセンブル */
- /**************************************/
- #define STO typesymbol
-
- /**********************************************************************/
- /* P-code ニーモニック表 */
- /**********************************************************************/
- static char instr[][4] =
- {
- /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
- /* 0x */ "lod","ldo","str","sro","sto","chk","ind","ldc","lda","dec",
- /* 1x */ "inc","mst","cup","ent","ret","...","ixa","equ","neq","geq",
- /* 2x */ "grt","leq","les","ujp","fjp","xjp","ejp","lap","adi","adr",
- /* 3x */ "sbi","sbr","sgs","flt","flo","trc","ngi","ngr","sqi","sqr",
- /* 4x */ "abi","abr","not","and","ior","dif","int","uni","inn","mod",
- /* 5x */ "odd","mpi","mpr","dvi","dvr","mov","lca","lao","stp","ord",
- /* 6x */ "chr","ujc","mms","msi","cui","bas","...","cka","tra","rou",
- /* 7x */ "nxt","nxd","...","...","...","new","dis","pge","eof","eol",
- /* 8x */ "rst","rwt","get","put","wrs","wrb","wri","wrr","wrc","wrf",
- /* 9x */ "wln","rdi","rdr","rdc","rln","trs","trw","tgt","tpt","atn",
- /*10x */ "sin","cos","exp","log","sqt"
- } ;
-
- /******* ニーモニック対応のエントリ表 ********/
- static struct entry {
- void (*func)(void) ;
- } OP[] = {
- /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
- /* 0x */ PTN1, PTN6 ,PTN1, PTN6, STO , CHK , PTN6, LDC , PTN2, PTN7,
- /* 1x */ PTN7, PTN3, PTN4, ENT , RET , PTN0, IXA , PTN5, PTN5, PTN5,
- /* 2x */ PTN5, PTN5, PTN5, PTN8, PTN8, PTN0, PTN4, PTN8, PTN0, PTN0,
- /* 3x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0,
- /* 4x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0,
- /* 5x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN2, LCA , PTN9, PTN0, ORD ,
- /* 6x */ PTN0, PTN0, PTN3, PTN0, PTN3, PTN3, PTN0, PTN0, PTN3, PTN0,
- /* 7x */ PTN7, PTN7, PTN0, PTN0, PTN0, PTN9, PTN9, PTN3, PTN3, PTN3,
- /* 8x */ PTN0, PTN0, PTN0, PTN0, PTN2, PTN3, PTN3, PTN3, PTN3, PTN3,
- /* 9x */ PTN3, PTN3, PTN3, PTN3, PTN3, PTN3, PTN3, PTN3, PTN3, PTN0,
- /*10x */ PTN0, PTN0, PTN0, PTN0, PTN0
- } ;
-
- /***************************************/
- /* 1行アセンブル処理 */
- /***************************************/
- static void assemble(void)
- {
- char name[4];
-
- *name = (char)readc() ; /* 1文字目 */
- *(name+1) = (char)readc() ; /* 2文字目 */
- *(name+2) = (char)readc() ; /* 3文字目 */
- *(name+3) = '\0' ;
- if(!eoln()) ch=readc();
- /* そこで行が終わってなければ次の文字を読む */
-
- cd.op = -1 ;
- while(strcmp(instr[++cd.op],name)) ;/* instructionよりopを決定 */
- /* このようなリニアサーチはスピードが遅いので改良しよう */
-
- cd.p = 0 ;
- cd.q = 0 ;
- OP[cd.op].func() ; /* opに対応したアセンブル */
-
- store[pc++].vo = cd ; /* メモリに格納 */
- }
-
- /********** generate() : 行の最初に呼ばれる処理 **********/
- static void generate(void)
- {
- short i ; /* 作業カウンタ */
- char progname[33] ; /* プログラム名 */
- char filename[33] ; /* ファイル名 */
- short fileadr ; /* ファイルアトレス */
- short filesize ; /* バッファ変数の大きさ */
-
- for(;;) {
- ch=readc(); /* 行の最初の文字を読む */
- switch(ch) {
- case ' ' : assemble(); /* 通常命令 その行をアセンブル*/
- break ;
-
- case ';' : /* 注釈行を無視 */
- break ;
-
- case 'L' : update() ; /* label登録 */
- break ;
-
- case 'V' : store[entpc].vo.p = (unsigned char)readi() ;
- store[entpc].vo.q = (short) readi() ;
- break ;
-
- case 'F' : /* ファイルアドレス */
- readc() ; /* 空白を読み飛ばす */
- i=0 ;
- while((ch=readc()) != ' ') /* ファイル名取得 */
- filename[i++] = (char)ch ;
- filename[i++] = '\0' ;
- readc() ; /* 空白を読み飛ばす*/
- fileadr = (short)readi() ; /* ファイルアトレス */
- putobject((char*)&fileadr,sizeof(fileadr));/* 書出 */
- filesize = (short)readi(); /* バッファサイズ */
- putobject((char*)&filesize,sizeof(filesize));/* 書出*/
- putobject(filename,i) ; /* ファイル名書出 */
- break ;
-
- case 'N' : /* プログラム名 */
- readc() ; /* 空白を読み飛ばす */
- i=0 ;
- while(!eoln()) /* プログラム名取得 */
- progname[i++] = (char)readc() ;
- progname[i++] = '\0' ;
- putobject(progname,i);/* 書出 */
- break ;
-
- case 'Q' : return ; /* アセンブル終わり */
- }
- readln() ; /* 行の残りを読み飛ばし */
- }
- }
-
-
- /*****************************************/
- /* assemblelist() : アセンブルリスト出力 */
- /*****************************************/
- static void assemblelist(void)
- {
- reset(PcodeSourceName) ; /* P-codeソースファイルのオープン */
-
- printf("\n ADDR OP P Q P-code source statement\n");
- printf( "================================================\n");
-
- pc = 0 ;
-
- for(;;) {
- ch=readc(); /* 行の最初の文字 */
- switch(ch) {
- case ' ' : printf(" %4d: %3d %3d %6d %c",
- pc++, store[pc].vo.op, store[pc].vo.p ,
- store[pc].vo.q,ch);
- break;
- case ';' :
- case 'L' :
- case 'V' :
- case 'F' :
- case 'N' : printf("\t\t\t %c",ch) ;
- break;
- case 'Q' : printf("\t\t\t Q\n") ;
- if(codesize != objsize)
- printf(" %4d:\n ~: constant data\n %4d:\n",
- codesize,objsize-1) ;
- fclose(pcsfile) ; /* ソースファイルのクローズ */
- return;
- }
- while(!eoln()) putc(readc(),stdout) ;
- printf("\n") ;
- if(ferror(stdout)) paerr(8) ; /* 出力でエラーが発生した */
- readln() ;
- }
- }
-
- /***************************************/
- /* main() : P-codeアセンブラメイン処理 */
- /***************************************/
- short main(short argc,char *argv[])
- {
- codesize = atoi(argv[1]) ; /* 命令コードの数 */
- PcodeSourceName = argv[2] ; /* P-codeソースファイル名 */
- PcodeObjectName = argv[3] ; /* P-codeオブジェクトファイル名*/
- CompVersion = argv[4] ; /* コンパイラのバージョン */
- init(); /* 各種初期設定 */
- generate(); /* アセンブル */
- fclose(pcsfile) ; /* ソースファイルのクローズ */
-
- for(pc=0;pc<codesize;pc++) { /* qオペランドの補正処理 */
- cd.op = store[pc].vo.op ;
- if((/*lao*/ cd.op==57)||(/*ldox*/cd.op==1 || (105<=cd.op && cd.op<=109))
- ||(/*srox*/cd.op==3 || (120<=cd.op && cd.op<=124)))
- store[pc].vo.q += objsize ;
- }
-
- putobject((char*)&start,sizeof(start)) ; /* オブジェクト開始合図 */
- putobject((char*)store,objsize*sizeof(_store)) ; /* オブジェクト出力*/
- if(fflush(objfile) == EOF) paerr(3) ;
- if(fclose(objfile) == EOF) paerr(3) ;
- /* クローズできなければ書き込み失敗の可能性がある */
-
- fputs( " *** Assemble completed. ***\n",stderr);
- fprintf(stderr," *** code = %5d words constant data = %5d words ***\n",
- codesize, objsize-codesize);
-
- if(argc==6) assemblelist(); /* アセンブルリストの出力 */
-
- return(0) ; /* 正常終了 */
- }